/*
 * Copyright (c) 2005, 2014 vacoor
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package org.vacoor.nothing.demo.jackson.ser;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonStreamContext;
import com.fasterxml.jackson.core.io.CharTypes;
import com.fasterxml.jackson.core.io.CharacterEscapes;
import com.fasterxml.jackson.core.json.JsonWriteContext;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;

/**
 * 对于 Non-US-ASCII --> Unicode 该类是过时的, 可以通过 {@link com.fasterxml.jackson.core.JsonGenerator.Feature#ESCAPE_NON_ASCII} 来设置
 * <p/>
 * 定制json字符串字符引用
 * bug: 如果指定了该Serializer 对于特性,eg: 不序列化默认值,null不起作用
 * <p/>
 * 默认情况下, Jackson 并不会将non US-ASCII字符转换为Unicode形式 "\\uxxxx";
 * 这时,如果双方知道编码(eg: Http协议中通过请求头设置编码)则没有问题,
 * 如果接受一方不知道编码,或编码错误这是就会产生乱码, 此时如果使用Unicode形式则可以避免
 * Java 原生支持Unicode因此不用考虑反序列化时是Unicode的情况
 * 主要是序列化时的Unicode处理
 *
 * @deprecated
 */
@Deprecated
public class UnicodeStringSerializer extends JsonSerializer<String> {
    private static final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();
    /**
     * 获取0~128对应的Unicode字符转义表,表中有三类值
     * -1 -- 需要转换为Unicode
     * 0 -- 无需转义
     * >1 -- 需要简单转移,值为去掉'\'后的转移字母的ASCII码,eg: \t 存放 t的ascii码
     * 转义加'\'即可 "\\" + (char)code
     */
    private static final int[] ESCAPE_CODES = CharTypes.get7BitOutputEscapes();

    @Override
    public void serialize(String s, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
        JsonStreamContext context = gen.getOutputContext();
        if (context instanceof JsonWriteContext) {
            JsonWriteContext jwc = (JsonWriteContext) context;
            switch (jwc.writeValue()) {
                case JsonWriteContext.STATUS_OK_AFTER_COLON:
                    gen.writeRaw(':');
                    break;
                case JsonWriteContext.STATUS_OK_AFTER_COMMA:
                    gen.writeRaw(',');
                    break;
                case JsonWriteContext.STATUS_EXPECT_NAME:
                    throw new JsonGenerationException("Can not testWrite string value here");
            }
            //写入json值开头引号
            gen.writeRaw('"');
            for (char c : s.toCharArray()) {
                // > 128 , 对non us-ascii进行转换
                if (c < 0x80) {
                    int escape = ESCAPE_CODES[c];
                    // 不需要转义
                    if (CharacterEscapes.ESCAPE_NONE == escape) {
                        gen.writeRaw(c);
                        // 标准
                    } else if (CharacterEscapes.ESCAPE_STANDARD == escape) {
                        gen.writeRaw(getUnicodeString(c));
                        // 特殊
                    } else {
                        gen.writeRaw("\\" + (char) escape);
                    }
                } else {
                    gen.writeRaw(getUnicodeString(c));
                }
            }
            //写入json值结尾引号
            gen.writeRaw('"');
        }
    }

    protected static String getUnicodeString(char c) {
        return "\\u"
                // 取出4个字节转为16进制
                + HEX_CHARS[(c >> 12) & 0xF]
                + HEX_CHARS[(c >> 8) & 0xF]
                + HEX_CHARS[(c >> 4) & 0xF]
                + HEX_CHARS[c & 0xF];
    }

}
